#include "Session.h"
#include <boost/asio/spawn.hpp>
#include <iostream>

using namespace UTILS;

// TODO 1. 将m_ReadWriteMgr_变为unique_ptr
Session::Session(SerializaReadWritePtr sock) : m_ReadWriteMgr_(sock) {}

void Session::start() {
  auto self(shared_from_this());
  boost::asio::co_spawn(
      m_ReadWriteMgr_->socket().get_executor(), [self] { return self->read(); },
      boost::asio::detached);
}

void Session::stop() { m_ReadWriteMgr_->socket().close(); }

void Session::write(const uint32_t id, std::string data) {
  m_RPCData_.clear();
  m_RPCData_.emplace_back(id, data);
  m_ReadWriteMgr_->async_write(m_RPCData_,
                               std::bind(&Session::handle_write, this,
                                         boost::asio::placeholders::error));
}

boost::asio::awaitable<void> Session::read() {
  try {
    while (true) {
      boost::system::error_code ec;
      co_await m_ReadWriteMgr_->async_read(m_RPCData_, ec);
      if (!ec) {
        handle_read();
      } else {
        std::cerr << __FUNCTION__ << " read fail ec: " << ec << std::endl;
      }
    }
  } catch (std::exception &e) {
  }
}

void Session::handle_read() {
  if (m_readFunc_) {
    for (uint32_t i = 0; i < m_RPCData_.size(); ++i) {
      std::cout << __FUNCTION__ << " code: " << m_RPCData_[i].code
                << " data: " << m_RPCData_[i].data.size() << std::endl;
      m_readFunc_(m_RPCData_[i].data);
    }
  } else {
    throw std::invalid_argument("m_readFunc_ is null!!");
  }
}
void Session::handle_write(const boost::system::error_code &ec) {
  if (m_writeFunc_) {
    m_writeFunc_(ec);
  } else {
    throw std::invalid_argument("m_writeFunc_ is null!!");
  }
}

void Session::attachRead(const ReadFunc &func) { m_readFunc_ = func; }

void Session::attachWrite(const WriteFunc &func) { m_writeFunc_ = func; }
